#ifndef COMMON_H
	#define COMMON_H

	#include	"structs.h"
	#include	"zone.h"

	#ifdef __cplusplus
	extern "C"{
	#endif



	//#define		AUDIO_REC_ENABLED
	//#define		ENABLE_FRAME_CONTROL
	//#define		ENABLE_LOGGING
	//#define		ENABLE_SRAM_LOG_ANALYSIS
	#define		ENABLE_MOUSE	// required to use game editor

	#define		EDIT_MODE_TILE_LAYOUT		1
	#define		EDIT_MODE_BLOCK_MAPPINGS	2
	#define		EDIT_MODE_SOLIDITY			3
	#define		EDIT_MODE_OBJECT_LAYOUT		4

    #ifdef __GNUC__
	#define FUNCINLINE inline
	#else
	#define FUNCINLINE
	#endif



	char *program_filename;		// get from argv[0]

	char config_section[4][16];

	char show_version;
	char show_watermark;



	// COMPATIBILITY SETTINGS
	// 0 = Bug fixed
	// 1 = Sonic 1 method
	// 2 = Sonic 2 method
	// 3 = Sonic 3 method
	// 4 = Sonic 3K method
	char compat_super_sonic_countdown;		// correct ring countdown timing



	int mouse_z_previous;

	char camera_mode;

	char PlayDemo(signed char d);
	void RecordDemo(signed char d);

	//int fade_type;
	char fade_count;

	char edit_mode;
	char edit_selector;
	int edit_clipboard;
	char collision_color;

	char prompt;	// when 1, activates LoadZonePrompt()

	short demo_order[256];

	char zone_file_list[257][32];	// last one used for unlisted files
	char demo_file_list[10][32];
	signed char demo_number;

	int demo_size;
	unsigned char *demodata;

	#ifdef ENABLE_SRAM_LOG_ANALYSIS
		void AnalyzeSRAM();
		char sram_file_list[10][32];
		int sram_size;
		unsigned short sram_start;
		unsigned char *sramdata;
		char sram_master_key;
		char sram_segment_key[8];
		unsigned char sram_frame[64];
	#endif



	unsigned char titlecard_counter[63];
	char titlecard_phase[63];
	short titlecard_xpos[63];
	short titlecard_ypos[63];
	unsigned char *titlecard_data;
	char titlecard_sequence_end;
	FILE *titlecard_file;



	// For YM2612 emulation
	AUDIOSTREAM *stream;
	FILE *ym_log_file;
	char sfxbank[4];

	FUNCINLINE void ProcessSound();
	void ResetSound();
	void PlayPCM(short sound, char buffer, char mix);
	void PlayFM(short sound, char buffer, char mix);

	void StreamPCM(char ch, int *pos_left, int *pos_right, unsigned short *poll_left, unsigned short *poll_right, int *buffer_left, int *buffer_right);
	void StreamFM(char ch, int *pos, int *buffer_left, int *buffer_right);
	#ifdef AUDIO_REC_ENABLED
		void RecordPCM(short *sample_data);
	#endif

	#define FM_TYPE_NULL		-1
	#define FM_TYPE_GYM			0
	#define FM_TYPE_VGM			1
	#define FM_DAC_OFF			0
	#define FM_DAC_ON			1
	#define FM_REPEAT_OFF		0
	#define FM_REPEAT_ON		1

	#define PCM_TYPE_MONO		0
	#define PCM_TYPE_STEREO		1
	#define PCM_REPEAT_OFF		0
	#define PCM_REPEAT_ON		1

	int digi_card;
	char bgm_enable;	// not used yet
	char sfx_enable;	// not used yet
	unsigned char *fm_data;
	int fm_data_address[257];
	char fm_data_type[256];		// 0-GYM, 1-VGM, 2-WAV
	char fm_data_dac[256];		// 0-Off, 1-On
	char fm_data_repeat[256];	// 0-Off, 1-On
	char fm_data_ch_type[4];	// 0-GYM, 1-VGM, 2-WAV
	char fm_data_ch_repeat[4];	// 0-Off, 1-On
	int fm_data_pos[4];
	int fm_data_pos_start[4];	// used for VGM files to quickly find the beginning
	int fm_data_pos_dac[4];	// used for VGM files that use data banks
	int fm_data_pos_loop[4];	// used for VGM files that use looping
	int fm_data_address_dac[4];	// used for VGM files that use data banks
	unsigned short fm_data_wait[4];	// used for VGM wait counting
	unsigned short fm_data_sample[4];		// store DAC samples for VGM
	char fm_reset[4];		// clear some values when FM first starts
	char fm_track_number[4];		// easy way to track which track is playing
	unsigned short fm_fader[4];		// amount to subtract from "TL" on FM channels
	char fm_fade_out[4];		// 0-No, 1-Yes

	int fm_offset;	// used as counter for loading FM files
	int fm_size;	// used as counter for loading FM files

	unsigned char audio_compression;	// measured in 16ths
	signed char audio_volume;			// 31 is full on, -1 is full off
	//int audio_peak;

	char bgm_type;	// 0 - FM, 1 - PCM

	FILE *pcm_out;
	int pcm_record_pos;
	unsigned char *pcm_data;
	unsigned short pcm_data_poll[2][4];
	int pcm_data_pos[2][4];
	int pcm_data_pos_start[2][4];
	int pcm_data_address[257];
	char pcm_data_format_stereo[256];
	char pcm_data_ch_format_stereo[2][4];
	char pcm_data_repeat[256];	// 0-Off, 1-On
	char pcm_data_ch_repeat[2][4];	// 0-Off, 1-On

	int pcm_offset;	// used as counter for loading PCM files
	int pcm_size;	// used as counter for loading PCM files

	#define		FM_VOLUME			0.666667	// -3.5dB
	#define		DAC_VOLUME			0.333333	// -9.5dB

	float mix_volume;

	char smart_mix;


	#ifdef ENABLE_LOGGING
	char msglog[100000][32];
	char msglog_tabs[100000];
	int logline;
	signed char logtab;
	void TabLog(signed char tab);
	void WriteLog(const char *string, ...);
	void VarLog(short var);
	void RegLog();
	void RamLog(unsigned short addr);
	void DumpLog(const char *string, ...);
	void ResetLog();
	enum VarLogNames{
		VAR_ROUTINE,
		VAR_X_RADIUS,
		VAR_Y_RADIUS,
		VAR_X_POS,
		VAR_X_POS_PRE,
		VAR_Y_POS,
		VAR_Y_POS_PRE,
		VAR_X_VEL,
		VAR_Y_VEL,
		VAR_INERTIA,
		VAR_STATUS,
		VAR_ANGLE,
		VAR_ANIM,
		VAR_LAYER,
		VAR_VAR_TEMP,
		REG_A0, REG_A1, REG_A2, REG_A3,
		REG_A4, REG_A5, REG_A6, REG_A7,
		REG_D0, REG_D1, REG_D2, REG_D3,
		REG_D4, REG_D5, REG_D6, REG_D7,
		REG_SR, REG_PC
	};
	int var_temp;
	#endif

	char advance_frame;
	char Game_paused;

	FILE *DemoFile;
	int DemoCount;		// 0x668 for Sonic 2, 0x708 for Sonic 1 and Sonic 3
	//int DemoSize;
	int DemoPosition;
	unsigned char DemoFadeDelay;

	#ifdef ENABLE_SRAM_LOG_ANALYSIS
		FILE *SRAMFile;
		unsigned short SRAMCount;		// 0x668 for Sonic 2, 0x708 for Sonic 1 and Sonic 3
		unsigned short SRAMPosition;
	#endif



	void quit(int e);
	ZONE z;
	int ReadBlock(ZONE *z, unsigned short x, unsigned short y);
	short ReadBackBlock(ZONE *z, unsigned short x, unsigned short y);



	unsigned char unlisted_zone;	// special condition for loading unlisted files
	unsigned char zone;		// 0-255	(8 bits)
	unsigned char act;		// 0-7		(3 bits)
	unsigned char stage;	// 0-4		(2 bits)

	unsigned char demo;
	char demo_mode;



	#define STATE_DIRECTION		0x1
	#define STATE_FLOATING		0x2
	#define STATE_SPINNING		0x4
	#define STATE_STATIC		0x8
	#define STATE_AUTO			0x10
	#define STATE_PUSHING		0x20
	#define STATE_UNDER_WATER	0x40
	#define STATE_UNDEFINED		0x80

	// uuuuuuup BPtttttt fmbbbbbb bbbbbbbb
	#define BMAP_BLOCK			0x3FFF
	#define BMAP_MIRROR			0x4000
	#define BMAP_FLIP			0x8000
	#define BMAP_TRANSLUCENCY	0x3F0000
	#define BMAP_PLATFORM		0x400000
	#define BMAP_BARRIER		0x800000
	#define BMAP_PLANE			0x1000000
	#define BMAP_UNDEFINED		0xFE000000



	unsigned char paused;

	unsigned char frame_skip;
	// 0 = 60 fps
	// 1 = 30 fps
	// 2 = 20 fps
	// 3 = 15 fps
	// 4 = 12 fps
	// 5 = 10 fps

	char draw_frame; // used to determine when to draw sprites with frame skip

	char full_screen;

	unsigned short screen_resolution_x;
	unsigned short screen_resolution_y;
	// e.g. 320x224

	unsigned short screen_padding_x;
	unsigned short screen_padding_y;
	// e.g. 0x16	(320+0=320, 224+16=240)

	unsigned short screen_offset_x;
	unsigned short screen_offset_y;
	// e.g. 0x8		(center 320x224 screen in 320x240 window)

	unsigned short screen_frame_x;
	unsigned short screen_frame_y;
	// e.g. 320x112

	unsigned short screen_buffer_x;
	unsigned short screen_buffer_y;
	// e.g. 352x112

	signed char screen_scale_x;
	signed char screen_scale_y;
	signed char screen_double_x;
	signed char screen_double_y;

	//char screen_interlace_x;
	//char screen_interlace_y;

	char vsync_enable;

	volatile int close_button_pressed;

	//unsigned char sound_number;

	char debug_show_object_nodes;
	short number_of_objects_in_memory;

	char key_m_previously_pressed;
	char key_n_previously_pressed;

	unsigned int ring_anim_counter;

	volatile char ticCounter60L;			// Logic (reset to 0 when ticCounter60R is 60)
	volatile unsigned char fps;
	char show_fps;
	unsigned int ticCounterL;				// Logic
	volatile unsigned int ticCounterR;		// Real-time
	volatile unsigned char ticCounter60R;	// Real-time % 60
	volatile char ticUpdated;
	volatile char waitCounter;

	//char frames;	// 0-3

	int water_current_height;	// current height of water
	short water_target;			// height for water to move to
	int water_direction;
	signed char water_accel;

	short counter_fe74;
	int counter_fe74_direction;
	signed short counter_fe74_accel;

	enum DrawingMode
	{
		NORMAL,
		MIRROR,
		FLIP,
		ROTATE
	};

	CELL background_cell;

	char num_of_players;
	char num_of_frames;

	BINDING key_bind[4];
	PLAYER player[16];
	PLAYER init_player;

	BITMAP *LayerB[4];
	BITMAP *LayerL[4];
	BITMAP *LayerH[4];
	BITMAP *LayerSH[4];
	BITMAP *LayerM;

	PLAYER *p;
	unsigned char frame;

	int composite;
	int bmap;
	int block;
	int tmap;
	int wmap;
	int palette_val;
	int composite_count;
	int bmap_count;
	int block_count;
	int tmap_count;
	int wmap_count;
	int palette_count;
	unsigned int composite_ptr;
	unsigned int bmap_ptr;
	unsigned int block_ptr;
	unsigned int tmap_ptr;
	unsigned int wmap_ptr;
	unsigned int palette_ptr;

	int tilesize;
	int tiles_x_short;
	int tiles_x_long;
	int tiles_y;

	unsigned short blocks_x;
	unsigned short blocks_y;



	unsigned char num_of_cells;
	unsigned char num_of_filters;
	unsigned short cells_ptr;
	unsigned short filters_ptr;
	unsigned short bg_rgb_color;
	unsigned char filter_a;
	unsigned char filter_b;
	unsigned char filter_a_speed;
	unsigned char filter_b_speed;
	CELL *cell_data;

	#ifdef __cplusplus
	}
	#endif
#endif
